Official docker images are published on docker hub for AMD64, ARMv7 and ARM64/v8: https://hub.docker.com/r/triliumnext/trilium/
Ensure Docker is installed on your system.
If you need help installing Docker, reference the Docker Installation Docs
Note: Trilium's Docker container requires root privileges to operate correctly.
wget https://raw.githubusercontent.com/TriliumNext/Trilium/master/docker-compose.yml
Optionally, edit the docker-compose.yml file
to configure the container settings prior to starting it. Unless configured
otherwise, the data directory will be ~/trilium-data and
the container will be accessible at port 8080.
Run the following command to start the container in the background:
docker compose up -d
To pull the image, use the following command, replacing [VERSION] with
the desired version or tag, such as v0.91.6 or
just latest. (See published tag names at
https://hub.docker.com/r/triliumnext/trilium/tags.):
docker pull triliumnext/trilium:v0.91.6
Warning: Avoid using the "latest" tag, as it may automatically upgrade your instance to a new minor version, potentially disrupting sync setups or causing other issues.
Trilium requires a directory on the host system to store its data. This directory must be mounted into the Docker container with write permissions.
Run the container to make it accessible only from the localhost. This setup is suitable for testing or when using a proxy server like Nginx or Apache.
sudo docker run -t -i -p 127.0.0.1:8080:8080 -v ~/trilium-data:/home/node/trilium-data triliumnext/trilium:[VERSION]
docker ps.127.0.0.1:8080.To make the container accessible only on your local network, first create a new Docker network:
docker network create -d macvlan -o parent=eth0 --subnet 192.168.2.0/24 --gateway 192.168.2.254 --ip-range 192.168.2.252/27 mynet
Then, run the container with the network settings:
docker run --net=mynet -d -p 127.0.0.1:8080:8080 -v ~/trilium-data:/home/node/trilium-data triliumnext/trilium:-latest
To set a different user ID (UID) and group ID (GID) for the saved data,
use the USER_UID and USER_GID environment
variables:
docker run --net=mynet -d -p 127.0.0.1:8080:8080 -e "USER_UID=1001" -e "USER_GID=1001" -v ~/trilium-data:/home/node/trilium-data triliumnext/trilium:-latest
Find the local IP address using docker inspect [container_name] and
access the service from devices on the local network.
docker ps
docker inspect [container_name]
To allow access from any IP address, run the container as follows:
docker run -d -p 0.0.0.0:8080:8080 -v ~/trilium-data:/home/node/trilium-data triliumnext/trilium:[VERSION]
Stop the container with docker stop <CONTAINER ID>,
where the container ID is obtained from docker ps.
For a custom data directory, use:
-v ~/YourOwnDirectory:/home/node/trilium-data triliumnext/trilium:[VERSION]
If you want to run your instance in a non-default way, please use the
volume switch as follows: -v ~/YourOwnDirectory:/home/node/trilium-data triliumnext/trilium:<VERSION>.
It is important to be aware of how Docker works for volumes, with the first
path being your own and the second the one to virtually bind to. https://docs.docker.com/storage/volumes/ The
path before the colon is the host directory, and the path after the colon
is the container's path. More details can be found in the Docker Volumes Documentation.
The --user directive is unsupported. Instead,
use the USER_UID and USER_GID environment
variables to set the appropriate user and group IDs.
If you are having timezone issues and you are not using docker-compose,
you may need to add a TZ environment variable
with the TZ identifier of
your local timezone.
If you would prefer to run Trilium without having to run the Docker container
as root, you can use either of the provided
Debian (default) and Alpine-based images with the rootless tag.
If you're unsure, stick to the “rootful” Docker image referenced above.
Below are some commands to pull the rootless images:
# For Debian-based image
docker pull triliumnext/trilium:rootless
# For Alpine-based image
docker pull triliumnext/trilium:rootless-alpine
Running containers as non-root is a security best practice that reduces the potential impact of container breakouts. If an attacker manages to escape the container, they'll only have the permissions of the non-root user instead of full root access to the host.
The rootless Trilium image:
trilium) during
build time--user flagentrypoint script# Run with default UID/GID (1000:1000)
docker-compose -f docker-compose.rootless.yml up -d
# Run with custom UID/GID (e.g., match your host user)
TRILIUM_UID=$(id -u) TRILIUM_GID=$(id -g) docker-compose -f docker-compose.rootless.yml up -d
# Specify a custom data directory
TRILIUM_DATA_DIR=/path/to/your/data TRILIUM_UID=$(id -u) TRILIUM_GID=$(id -g) docker-compose -f docker-compose.rootless.yml up -d
# Build the image
docker build -t triliumnext/trilium:rootless -f apps/server/Dockerfile.rootless .
# Run with default UID/GID (1000:1000)
docker run -d --name trilium -p 8080:8080 -v ~/trilium-data:/home/trilium/trilium-data triliumnext/trilium:rootless
# Run with custom UID/GID
docker run -d --name trilium -p 8080:8080 --user $(id -u):$(id -g) -v ~/trilium-data:/home/trilium/trilium-data triliumnext/trilium:rootless
TRILIUM_UID: UID to use for the container
process (passed to Docker's --user flag)TRILIUM_GID: GID to use for the container
process (passed to Docker's --user flag)TRILIUM_DATA_DIR: Path to the data directory
inside the container (default: /home/node/trilium-data)For a complete list of configuration environment variables (network settings, authentication, sync, etc.), see Configuration (config.ini or environment variables).
If you encounter permission issues with the data volume, ensure that:
TRILIUM_UID and
TRILIUM_GIDto match the owner of the host directory# For example, if your data directory is owned by UID 1001 and GID 1001:
TRILIUM_UID=1001 TRILIUM_GID=1001 docker-compose -f docker-compose.rootless.yml up -d
usermod/groupmod commandsTwo rootless variants are provided:
apps/server/Dockerfile.rootless
apps/server/Dockerfile.alpine.rootless
If you would prefer, you can also customize the UID/GID at build time:
# For Debian-based image with custom UID/GID
docker build --build-arg USER=myuser --build-arg UID=1001 --build-arg GID=1001 \
-t triliumnext/trilium:rootless-custom -f apps/server/Dockerfile.rootless .
# For Alpine-based image with custom UID/GID
docker build --build-arg USER=myuser --build-arg UID=1001 --build-arg GID=1001 \
-t triliumnext/trilium:alpine-rootless-custom -f apps/server/Dockerfile.alpine.rootless .
Available build arguments:
USER: Username for the non-root user (default:
trilium)UID: User ID for the non-root user (default:
1000)GID: Group ID for the non-root user (default:
1000)